package com.gzhryc.common;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * ZIP解压缩工具类
 * @author 张浩
 * @version 1.0.10
 */
public class ZipTools {
	
	public static final String EXT = ".zip";
    private static final int BUFFER = 1024;

    /**
     * 压缩(不支持中文文件名)
     * @param dir
     * @param targetPath
     * @return
     */
	public static boolean compress(File dir,String targetPath){
		try{
			if(dir.exists() && dir.isDirectory() && StringUtils.isNotBlank(targetPath)){
				OutputStream out = null;
				if(targetPath.matches("^.*\\.zip$")){
					File targetFile = new File(targetPath);
					if(!targetFile.exists()){
						targetFile.getParentFile().mkdirs();
						targetFile.createNewFile();
						out = FileUtils.openOutputStream(targetFile);
					}else{
						out = FileUtils.openOutputStream(targetFile);
					}
				}else{
					File targetFile = new File(targetPath + "/" + dir.getName()+EXT);
					targetFile.getParentFile().mkdirs();
					targetFile.createNewFile();
					out = FileUtils.openOutputStream(targetFile);
				}
				ZipOutputStream zipOut = new ZipOutputStream(out);
				//zipOut.setEncoding("UTF-8");
				write(dir,zipOut,"");
				/*
				for(File child:dir.listFiles()){
					write(child,zipOut,"");
				}
				*/
				zipOut.finish();
				zipOut.close();
				return true;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return false;
	}
	
	private static void write(File file,ZipOutputStream out,String parentPath) throws IOException{
		if(file.isDirectory()){
			File[] children = file.listFiles();
			if(children.length > 0){
				for(File child:file.listFiles()){
					write(child,out,parentPath + file.getName() + "/");
				}
			}else{
				ZipEntry entry = new ZipEntry(parentPath +file.getName() + "/");
				out.putNextEntry(entry);
				out.closeEntry();
			}
		}else{
			ZipEntry entry = new ZipEntry(parentPath +file.getName());
			out.putNextEntry(entry);
			out.write(FileUtils.readFileToByteArray(file));
			out.closeEntry();
		}
	}

    /** 
     * 解压缩(不支持中文文件名)
     * @param srcPath  源文件路径 
     * @throws Exception 
     */  
    public static void decompress(String srcPath) throws Exception {  
        File srcFile = new File(srcPath);
        decompress(srcFile);  
    }  
  
    /** 
     * 解压缩(不支持中文文件名)
     * @param srcFile 
     * @throws Exception 
     */  
    public static void decompress(File srcFile) throws Exception {  
        String basePath = srcFile.getParent();
        decompress(srcFile, basePath);  
    }  
  
    /** 
     * 解压缩(不支持中文文件名)
     * @param srcFile 
     * @param destFile 
     * @throws Exception 
     */  
    public static void decompress(File srcFile, File destFile) throws Exception {  
        CheckedInputStream cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());  
        ZipInputStream zis = new ZipInputStream(cis);  
        decompress(destFile, zis);  
        zis.close();  
    }  
  
    /** 
     * 解压缩(不支持中文文件名)
     * @param srcFile 
     * @param destPath 
     * @throws Exception 
     */  
    public static void decompress(File srcFile, String destPath)  
            throws Exception {  
        decompress(srcFile, new File(destPath));  
  
    }  
  
    /** 
     * 解压缩(不支持中文文件名)
     * @param srcPath  源文件路径 
     * @param destPath 目标文件路径 
     * @throws Exception 
     */  
    public static void decompress(String srcPath, String destPath)  
            throws Exception {  
        File srcFile = new File(srcPath);  
        decompress(srcFile, destPath);  
    }
  
    /** 
     * 解压缩
     * @param destFile  目标文件 
     * @param zis  ZipInputStream 
     * @throws Exception 
     */  
    private static void decompress(File destFile, ZipInputStream zis)  
            throws Exception {  
        ZipEntry entry = null;  
        while ((entry = zis.getNextEntry()) != null) {  
            // 文件  
            String dir = destFile.getPath() + File.separator + entry.getName();  
            File dirFile = new File(dir);  
            // 文件检查  
            fileProber(dirFile);  
            
            if (entry.isDirectory()) {  
                dirFile.mkdirs();  
            } else {  
                decompressFile(dirFile, zis);  
            }  
            zis.closeEntry();  
        }
    }  
  
    /** 
     * 文件探针 
     * 当父目录不存在时，创建目录！ 
     * @param dirFile 
     */  
    private static void fileProber(File dirFile) {  
        File parentFile = dirFile.getParentFile();  
        if (!parentFile.exists()) {  
            // 递归寻找上级目录  
            fileProber(parentFile);
            parentFile.mkdir();  
        }  
    }  
  
    /** 
     * 解压缩 
     * @param destFile    目标文件 
     * @param zis   ZipInputStream 
     * @throws Exception 
     */  
    private static void decompressFile(File destFile, ZipInputStream zis)  
            throws Exception {
        BufferedOutputStream bos = new BufferedOutputStream(  
                new FileOutputStream(destFile));  
        int count;  
        byte data[] = new byte[BUFFER];  
        while ((count = zis.read(data, 0, BUFFER)) != -1) {  
            bos.write(data, 0, count);  
        }  
        bos.close();  
    }  
}
